#ifndef  _WS_PACK_H_
#define  _WS_PACK_H_
#include <string>
#include <map>
#include <vector>
#include "cache.h"

using namespace std;
using namespace comm::sockcommu;

#define WS_MAX_HANDSHAKE_FRAME_SIZE (1024 * 1000)

class CWspack
{
private:
public:
    enum WSOpcodeType
    {
        WSOpcode_Continue = 0x0,
        WSOpcode_Text = 0x1,
        WSOpcode_Binary = 0x2,
        WSOpcode_Close = 0x8,
        WSOpcode_Ping = 0x9,
        WSOpcode_Pong = 0xA,
    };

    CWspack();
    ~CWspack();
    int recv_handshake(const char* data, unsigned int len);
    int pack_handshake_rsp(void);
    int recv_dataframe(const char* data, unsigned int len);
    int pack_dataframe(const char* data, unsigned int len);
    const uint8_t get_length_type(void);
    std::string& get_handshakersp(void){ return m_handshakeRsp;}
    unsigned char get_fin(void){return m_fin;}
    void set_fin(uint8_t fin) { m_fin = fin; }
    char* data(void){return m_r.data();}
    unsigned int entire_data_len(void){return m_r.data_len();}
    const uint8_t get_opcode() { return m_opcode; }
    void set_opcode(uint8_t opcode) { m_opcode = opcode; }
    const uint8_t get_mask() { return m_mask; }
    void set_mask(uint8_t mask) { m_mask = mask; }
    uint8_t * get_mask_key(void){return m_masking_key;}
    unsigned int get_mask_key_len(void) {return sizeof(m_masking_key);}
    void set_mask_key(uint8_t *mask_key, unsigned int len){::memcpy(m_masking_key, mask_key, min(len, (unsigned int)sizeof(m_masking_key)));}
    void clear(void);

private:
    int fetch_hs_element(const std::string &msg);
    int fetch_frame_info(const char* data, unsigned int len);
    int fetch_payload(const char* data, unsigned int len, unsigned int headlen);
    std::map<std::string, std::string> m_params;
    std::string m_handshakeRsp;
    CRawCache   m_r;
    const std::string get_param(const std::string &name) const
    {
        std::map<std::string, std::string>::const_iterator it =
            m_params.find(name);
        if (it != m_params.end())
        {
            return it->second;
        }
        return std::string();
    }

    uint8_t m_fin;
    uint8_t m_rsv1;
    uint8_t m_rsv2;
    uint8_t m_rsv3;
    uint8_t m_opcode;
    uint8_t m_mask;
    //uint8_t m_length_type;
    uint8_t m_masking_key[4];
    unsigned int m_payload_length;
};



#endif